# 导入必要的库
import matplotlib.pyplot as plt  # 用于绘图
import numpy as np  # 用于数值计算
from collections import Counter  # 用于计数
from pinecone import Pinecone, ServerlessSpec

# 初始化 Pinecone
pc = Pinecone(api_key="pcsk_5kxYS1_7Wqt2wKhRJntVmYMMVVEvSxbYVJCTEM3Z1RK3viMkFVpjFLTJyA4xaHZdhGQajC")

# 索引名称
index_name = "mnist-index"

# 连接到索引
index = pc.Index(index_name)

# 创建一个手写数字 3 的图像
# 使用 numpy 数组表示一个 8x8 的二维图像
# 255 表示白色像素,0 表示黑色像素
digit_3 = np.array(
    [[0, 0, 255, 255, 255, 255, 0, 0],
     [0, 0, 0, 0, 0, 255, 0, 0],
     [0, 0, 0, 0, 0, 255, 0, 0],
     [0, 0, 0, 255, 255, 255, 0, 0],
     [0, 0, 0, 0, 0, 255, 0, 0],
     [0, 0, 0, 0, 0, 255, 0, 0],
     [0, 0, 0, 0, 0, 255, 0, 0],
     [0, 0, 255, 255, 255, 255, 0, 0]]
)

# 将图像像素值从 0-255 的范围缩放到 0-16 的范围
# 这是为了匹配 MNIST 数据集中使用的像素值范围
digit_3_flatten = (digit_3 / 255.0) * 16

# 将二维图像数组展平成一维列表
# 这是因为 Pinecone 要求输入向量是一维的
query_data = digit_3_flatten.ravel().tolist()

# 使用准备好的查询向量在 Pinecone 索引中执行搜索
results = index.query(
    vector=query_data,
    top_k=11,  # 返回距离最近的 11 个结果
    include_metadata=True  # 同时返回每个向量的元数据(包括标签)
)

print(f"查询结果: {results}")
print(f"匹配数量: {len(results['matches'])}")

# 从搜索结果中提取每个匹配项的标签
if results['matches']:
    labels = [match['metadata']['label'] for match in results['matches']]
else:
    labels = []
    print("警告: 没有匹配的搜索结果！")

# 打印每个匹配结果的详细信息
for match, label in zip(results['matches'], labels):
    print(f"id: {match['id']}, distance: {match['score']}, label: {label}")

# 使用投票机制确定最终的分类结果
if labels:
    final_prediction = Counter(labels).most_common(1)[0][0]
else:
    final_prediction = "无匹配结果"
    print("无法进行分类，因为没有找到匹配的搜索结果")

# 使用 matplotlib 显示查询图像和预测结果
plt.imshow(digit_3, cmap='gray')  # 显示灰度图像
plt.title(f"Predicted digit: {final_prediction}", size=15)  # 设置标题,显示预测结果
plt.axis('off')  # 关闭坐标轴
plt.show()  # 展示图像
